Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BE-586 | Claimbot #524

Open
wants to merge 34 commits into
base: v26.x
Choose a base branch
from
Open

BE-586 | Claimbot #524

wants to merge 34 commits into from

Conversation

deividaspetraitis
Copy link
Collaborator

@deividaspetraitis deividaspetraitis commented Oct 8, 2024

This PR introduces The Orderbook Claimbot plugin. Orderbook Claimbot plugin is a plugin that claims filled order book orders.

It scans all active orders for each order book determining which orders have been filled and need to be claimed. At the moment order is said to be claimable if it is filled 98 percent or more. In order for an order book to be processed to claim its active orders it must be canonical as per SQS definition.

At this moment there is a few drawbacks of current implementation that can be improved in future, such as for example claiming orders from multiple orderbooks within single transaction, or using test keyring alternative.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced the Orderbook Claim Bot for processing claimable orders.
    • Added new targets for managing the Orderbook Claim Bot in the configuration.
    • New README documentation for the Orderbook Claim Bot detailing setup and usage.
  • Bug Fixes

    • Updated naming conventions for consistency across the Orderbook plugins.
  • Documentation

    • Enhanced clarity and specificity in the README files for both the Orderbook Claim Bot and Filler Bot.
  • Chores

    • Improved the backup script for configuration files to prevent overwriting existing backups.

@deividaspetraitis deividaspetraitis changed the title FE-586 | Claimbot BE-586 | Claimbot Oct 8, 2024
Copy link
Member

@p0mvn p0mvn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good - nice work.

Once the solution is cleaned up with tests added, could you please also link a few DataDog trace samples of processing the block as claimbot?

@deividaspetraitis deividaspetraitis self-assigned this Oct 16, 2024
@deividaspetraitis deividaspetraitis marked this pull request as ready for review October 25, 2024 14:27
Copy link
Contributor

coderabbitai bot commented Oct 25, 2024

Walkthrough

The pull request introduces a series of modifications across multiple files to enhance the functionality of orderbook plugins, specifically focusing on the addition of an "Orderbook Claim Bot." Key changes include updates to the Makefile for new management targets, integration of the claim bot plugin in the sidecar_query_server.go, and enhancements to configuration files. New structures and methods are defined to handle claimable orders, and a Docker Compose file is added for service management. Overall, these changes expand the capabilities of the orderbook management system.

Changes

File Path Change Summary
Makefile - Added targets: orderbook-claimbot-start, orderbook-claimbot-stop
- Updated echo statements for consistency.
app/sidecar_query_server.go - Integrated orderbookclaimbot plugin with new instantiation logic.
config.json - Added "grpc-ingester" section with plugins: orderbook-fillbot-plugin, orderbook-claimbot-plugin.
domain/config.go - Updated Config struct to include two OrderBookPluginConfig instances.
- Modified PluginFactory function.
domain/orderbook/plugin/config.go - Removed OrderBookPluginName constant.
- Added constants: OrderbookFillbotPlugin, OrderbookClaimbotPlugin.
ingest/usecase/plugins/orderbook/claimbot/.env - Updated OSMOSIS_KEYRING_KEY_NAME variable (no-op).
ingest/usecase/plugins/orderbook/claimbot/README.md - Added documentation for the Orderbook Claimbot Plugin, including setup and configuration instructions.
ingest/usecase/plugins/orderbook/claimbot/config.go - Introduced Config struct and NewConfig function for the claimbot.
ingest/usecase/plugins/orderbook/claimbot/docker-compose.yml - New Docker Compose file for managing related services.
ingest/usecase/plugins/orderbook/claimbot/order.go - Introduced order processing logic for identifying claimable orders.
ingest/usecase/plugins/orderbook/claimbot/orderbook.go - Added getOrderbooks function to retrieve canonical orderbooks.
ingest/usecase/plugins/orderbook/claimbot/plugin.go - Implemented claimbot struct and methods for processing claims at the end of each block.
ingest/usecase/plugins/orderbook/claimbot/tx.go - Added functions for preparing and sending batch claim transactions.
ingest/usecase/plugins/orderbook/fillbot/README.md - Updated plugin name in documentation for clarity.
ingest/usecase/plugins/orderbook/fillbot/create_copy_config.sh - Modified script to check for existing backup before proceeding.

Possibly related PRs

Suggested reviewers

  • p0mvn

"In the burrow where the code does flow,
A claim bot hops, ready to grow.
With echoes clear and plugins bright,
Orderbooks dance in the moonlight.
Let's claim those orders, one by one,
A joyful task, oh what fun!" 🐇✨


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 8a8ef15 and d298179.

📒 Files selected for processing (1)
  • ingest/usecase/plugins/orderbook/claimbot/plugin.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • ingest/usecase/plugins/orderbook/claimbot/plugin.go

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

coderabbitai[bot]

This comment was marked as outdated.

},
```

Configure the key on a test keyring, and set the following environment variables:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for lack of context here, key is named as local but then what is meant by local.info

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's full name of the key on the disk as per my understanding, if you would list contents you would see something like that:

ll ~/.osmosisd/keyring-test/
total 16
drwxr-xr-x 2 root root 4096 Oct 25 13:54 ./
drwxr-xr-x 7 root root 4096 Oct 25 13:40 ../
-rw------- 1 root root  537 Oct 25 13:54 abcd....address
-rw------- 1 root root  735 Oct 25 13:54 local.info

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for lack of context, should we consider any parallelization here? Guess we shouldn't due to business requirements and so I'm just asking.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is possible to apply parallelization for some calls, for example for procssing different orderbooks. Let me keep this conversation open, and let's see what @p0mvn thinks. In case we decide to do that I think we should create separate task for that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed with the direction of creating a separate task. This should be an easy win that allows us to avoid worrying about any processing latencies in the future.

Let's tackle it before completing the feature.

Copy link
Collaborator

@cryptomatictrader cryptomatictrader left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice work! Please consider the comments left. Thank you!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (4)
log/logger.go (1)

40-43: Fix incorrect method documentation

The comment "Warn implements Logger" is incorrect for the Named method.

-// Warn implements Logger.
+// Named implements Logger.
 func (l *NoOpLogger) Named(s string) Logger {
ingest/usecase/plugins/orderbook/claimbot/plugin.go (3)

36-40: Convert blockInclusionWaitTime to a constant.

Since blockInclusionWaitTime is a fixed value, it should be defined as a constant alongside other constants for better maintainability and clarity.

Apply this diff:

const (
    tracerName = "sqs-orderbook-claimbot"
+   blockInclusionWaitTime = 5 * time.Second
)

var (
    tracer        = otel.Tracer(tracerName)
    fillThreshold = osmomath.MustNewDecFromStr("0.98")
-   blockInclusionWaitTime = 5 * time.Second
)

153-154: Document the purpose of blockInclusionWaitTime.

While the sleep is necessary, its purpose should be better documented to explain why this specific duration was chosen and what issues it prevents.

Add a detailed comment explaining the rationale:

-       // Wait for block inclusion with buffer to avoid sequence mismatch
+       // Wait for block inclusion with a 5-second buffer to ensure the previous transaction
+       // is included in a block before sending the next one. This prevents sequence mismatch
+       // errors that can occur when transactions are sent too quickly in succession.
        time.Sleep(blockInclusionWaitTime)

23-28: Document plugin behavior during edge cases.

The plugin documentation should include information about:

  1. How it handles chain upgrades
  2. Behavior during network connectivity issues
  3. Recovery mechanisms for failed transactions
  4. Any assumptions about chain block times relative to blockInclusionWaitTime

This will help operators understand the plugin's limitations and requirements.

Add comprehensive documentation to the struct:

-// claimbot is a claim bot that processes and claims eligible orderbook orders at the end of each block.
-// Claimable orders are determined based on order filled percentage that is handled with fillThreshold package level variable.
+// claimbot is a claim bot that processes and claims eligible orderbook orders at the end of each block.
+// Claimable orders are determined based on order filled percentage that is handled with fillThreshold package level variable.
+//
+// Edge Cases:
+// - Chain Upgrades: The plugin will stop processing during upgrades and resume after chain restart
+// - Network Issues: Failed transactions will be logged but not retried automatically
+// - Block Times: Assumes minimum block time > blockInclusionWaitTime to prevent transaction sequence issues
+// - Recovery: Manual intervention may be required if transactions fail consistently
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0ff913b and 3216bb1.

📒 Files selected for processing (3)
  • ingest/usecase/plugins/orderbook/claimbot/config.go (1 hunks)
  • ingest/usecase/plugins/orderbook/claimbot/plugin.go (1 hunks)
  • log/logger.go (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • ingest/usecase/plugins/orderbook/claimbot/config.go
🔇 Additional comments (3)
log/logger.go (3)

11-11: LGTM: Named logger interface addition

The addition of the Named method to the Logger interface follows standard logging patterns and enables hierarchical logging contexts.


128-130: LGTM: Return type change promotes better abstraction

The change to return the Logger interface instead of concrete type is a good practice that promotes loose coupling.


11-11: Verify logger usage patterns across the codebase

The addition of the Named method and changes to logger instantiation might require updates in other parts of the codebase.

Also applies to: 73-77, 128-130

✅ Verification successful

Let me gather more information about the logger implementation and its usage patterns.


Based on the comprehensive analysis of the logger usage across the codebase, I can now provide the final response:

The Named method addition is safe and correctly implemented

The Named method is already being used in the codebase, specifically in the claimbot configuration:

  • ingest/usecase/plugins/orderbook/claimbot/config.go: Logger: logger.Named("claimbot")

The logger interface and implementation are self-contained within the log package, and the Named method is a standard logging pattern for creating scoped loggers. The addition of this method doesn't require any mandatory updates across the codebase as:

  1. It's an optional method that enhances logger functionality
  2. Existing logger usage patterns remain unaffected
  3. The implementation follows the standard logging pattern of creating named/scoped loggers
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check logger instantiation and usage patterns

# Check for direct zap.Logger usage that might need updating
echo "Checking for direct zap.Logger usage..."
rg --type go "zap\.Logger"

# Check for existing logger naming patterns that might use the new Named method
echo "Checking existing logger naming patterns..."
rg --type go "logger.*Named\("

Length of output: 444


Script:

#!/bin/bash
# Check the logger interface and implementation
echo "Checking logger interface and implementation..."
rg --type go -A 5 "type Logger interface"

# Check for all logger instantiations
echo "Checking logger instantiations..."
rg --type go "New(Logger|ZapLogger)"

# Check for all logger usages in the codebase
echo "Checking logger usages..."
rg --type go "logger\." -A 2

Length of output: 29969

Comment on lines +73 to +77
func (l *loggerImpl) Named(s string) Logger {
return &loggerImpl{
zapLogger: *l.zapLogger.Named(s),
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add nil check for zapLogger

The current implementation could panic if zapLogger is nil. Consider adding a nil check for defensive programming.

 func (l *loggerImpl) Named(s string) Logger {
+	if l == nil || &l.zapLogger == nil {
+		return &NoOpLogger{}
+	}
 	return &loggerImpl{
 		zapLogger: *l.zapLogger.Named(s),
 	}
 }

Committable suggestion was skipped due to low confidence.

Copy link
Member

@p0mvn p0mvn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Left comment - please take a look

Comment on lines +72 to +77
batchClaim := struct {
BatchClaim struct {
Orders [][]int64 `json:"orders"`
} `json:"batch_claim"`
}{
BatchClaim: struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's address code rabbit rec below

Comment on lines +83 to +86
orderbooks, err := getOrderbooks(o.config.PoolsUseCase, blockHeight, metadata)
if err != nil {
return err
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having this as a function and propagating pools use case as an arg, why not make this be a method on the pools use case?

Comment on lines +22 to +23
OrderbookUsecase mvc.OrderBookUsecase
OrderbookRepository orderbookdomain.OrderBookRepository
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should really only need the use case. Usecase encapsulates the repository. So all requests to the repository should be proxied through the use case.

This is an implementation of the MVC design pattern where the repository is the model.

Comment on lines +24 to +26
OrderBookClient orderbookgrpcclientdomain.OrderBookClient
AccountQueryClient authtypes.QueryClient
TxfeesClient txfeestypes.QueryClient
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider abstracting all of the chain clients behind a struct

Comment on lines +28 to +30
orderbookRepository orderbookdomain.OrderBookRepository,
orderBookClient orderbookgrpcclientdomain.OrderBookClient,
orderbookusecase mvc.OrderBookUsecase,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to my other comment, we should only need to pass orderbook use case and proxy requests to the repository through it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed with the direction of creating a separate task. This should be an easy win that allows us to avoid worrying about any processing latencies in the future.

Let's tackle it before completing the feature.

}

// processOrderbooksAndGetClaimableOrders processes a list of orderbooks and returns claimable orders for each.
func processOrderbooksAndGetClaimableOrders(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm seeing only this function being covered by tests but there are many downstream function of varying branching complexity.

Could we spend some time covering those with tests?

I think it would pay off in the long-term as it would make any possible refactors drastically easier under simpler test coverage

Comment on lines +155 to +156
// Wait for block inclusion with buffer to avoid sequence mismatch
time.Sleep(blockInclusionWaitTime)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider querying the sequence number at the beginning of the block and incrementing it in-memory. This should be fine since we have a lock on block processing. That is, if block X is being processed, block X+1 processing cannot start.

This would drastically speed up processing all orders within a block

Comment on lines +17 to +21
type order struct {
Orderbook domain.CanonicalOrderBooksResult
Orders orderbookdomain.Orders
Err error
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This abstraction name is confusing.

This is not an order but rather orderbook with its claimable orders.

I suggest renaming it accordingly as well as the variable identifiers to make the logic more readable.

Copy link

sonarcloud bot commented Oct 29, 2024

Quality Gate Failed Quality Gate failed

Failed conditions
40.5% Coverage on New Code (required ≥ 50%)

See analysis details on SonarCloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants